#include "log.h"

namespace sys {

Logger* Logger::_instance = NULL;

Logger* Logger::getInstance()
{
	if (_instance == NULL)
	{
		_instance = new Logger();
	}

	return _instance;
}

Logger::Logger()
{
	_min_level = SOCKET_DEBUG;
	_log_fp = NULL;
	_log_file = new char[MAX_FILENAME_LEN];
	memset(_log_file, 0, MAX_FILENAME_LEN);
	_log_buf = new char[LOG_BUF_SIZE];
	_mutex = new pthread_mutex_t;
	pthread_mutex_init(_mutex, NULL);
}

Logger::~Logger()
{
	if (_log_file != NULL)
	{
		delete [] _log_file;
		_log_file = NULL;
	}

	if (_log_buf != NULL)
	{
		delete [] _log_buf;
		_log_buf = NULL;
	}

	if (_log_fp != NULL)
	{
		fclose(_log_fp);
		_log_fp = NULL;
	}

	pthread_mutex_destroy(_mutex);
	if (_mutex != NULL)
	{
		delete _mutex;
		_mutex = NULL;
	}
}

bool Logger::initLogger(const char* fileName, LOG_LEVEL minLevel)
{
	strncpy(_log_file, fileName, MAX_FILENAME_LEN - 1);
	if (minLevel >= 0 && minLevel <= 4)
	{
		_min_level = minLevel;
	}

	_log_fp = fopen(_log_file, "a");
	if (_log_fp == NULL)
	{
		return false;
	}

	return true;
}

void Logger::writeLog(LOG_LEVEL level, int tid, const char* format, ...)
{
	if (level < _min_level)
		return;

	pthread_mutex_lock(_mutex);
	va_list valist;
	va_start(valist, format);
	set_log(level, tid, format, valist);
	va_end(valist);

	fputs(_log_buf, _log_fp);
	fflush(_log_fp);
	pthread_mutex_unlock(_mutex);
}


void Logger::writeLogNoLock(LOG_LEVEL level, int tid, const char* format, ...)
{
	if (level < _min_level)
		return;

	va_list valist;
	va_start(valist, format);
	set_log(level, tid, format, valist);
	va_end(valist);
	fputs(_log_buf, _log_fp);
	fflush(_log_fp);
}

void Logger::set_log(LOG_LEVEL level, int tid, const char* format,  va_list valist)
{
	char levStr[16];
	memset(levStr, 0, sizeof(levStr));

	switch(level)
	{
		case SOCKET_DEBUG:
		case DEBUG:
		strcpy(levStr, "DEBUG");
		break;

		case INFO:
		strcpy(levStr, "INFO");
		break;

		case WARN:
		strcpy(levStr, "WARN");
		break;

		case ERROR:
		strcpy(levStr, "ERROR");
		break;
	}

	if (_log_fp == NULL)
	{
		_log_fp = fopen(_log_file, "a");
	}

	memset(_log_buf, 0, LOG_BUF_SIZE);
	struct timeval now = {0, 0};
	gettimeofday(&now, NULL);
	struct tm* sys_tm = localtime(&(now.tv_sec));

	int n = snprintf(_log_buf, 128, "[TID:%d] %d-%02d-%02d %02d:%02d:%02d.%03lu[%s]",
		tid, sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday,
		sys_tm->tm_hour, sys_tm->tm_min, sys_tm->tm_sec, now.tv_usec / 1000, levStr);
	vsnprintf(_log_buf + n, LOG_BUF_SIZE  - n, format, valist);
}

















}